//
//  XMSModelTransform.m
//  
//
//  Created by wjxfhxy on 16/4/14.
//
//

#import "XMSModelTransform.h"

#import "XMSJSONTransformObj.h"

@interface XMSQueueDictionary (XMSModelTransformRegisterKeyType)

-(void)registerKey:(NSString*)key withProperty:(NSString *)property opType:(NSUInteger)opType;

@end

@implementation XMSQueueDictionary (XMSModelTransformRegisterKeyType)

-(void)registerKey:(NSString*)key withProperty:(NSString *)property opType:(NSUInteger)opType
{
    XMSModelTransformPair *pair = [[XMSModelTransformPair new] autorelease_mm];
    pair.key = key;
    pair.value = property.length > 0 ? property : nil;
    pair.opType = opType > 0 ? opType : XMSModelTransformOpTypeCommon1;
    
    [self addKvPairDirect:pair];
}

@end

@implementation XMSModelTransformPair

@synthesize propertyType = _propertyType;
@synthesize opType = _opType;

- (id)copyWithZone:(NSZone *)zone
{
    XMSModelTransformPair *pair = [super copyWithZone:zone];
    
    pair.propertyType = self.propertyType;
    pair.opType = self.opType;
    
    return pair;
}


@end

@implementation XMSModelTransform

static NSMutableDictionary *s_transPair = nil;

static XMSOSSpinLock *s_lock;

+(void)initialize
{
    s_transPair = [NSMutableDictionary new];
    
    s_lock = [XMSOSSpinLock new];
}

+(void)addTransPair:(XMSQueueDictionary*)transPair forModelIdentificationKey:(NSString*)key
{
    [s_lock lock:^
    {
        s_transPair[key] = transPair;
    }];
}

+(XMSQueueDictionary*)transPairForModelIdentificationKey:(NSString*)key
{
    __block XMSQueueDictionary *trasPair = nil;
    [s_lock lock:^
    {
        trasPair = s_transPair[key];
    }];
    return trasPair;
}

+(void)register
{
    [self registerModelClass:[self class] forOperationKeyType:^(XMSQueueDictionary *keyType)
    {
        void(^f)(NSString *key,NSString *property,NSUInteger opType) = ^(NSString *key,NSString *property,NSUInteger opType)
        {
            [keyType registerKey:key withProperty:property opType:opType];
        };
        [self registerModelTransformOperationKeyType:f];
    }];
}

+(void)registerModelClass:(Class)cls forOperationKeyType:(void(^)(XMSQueueDictionary* keyType))block
{
    XMSQueueDictionary *qd = [[XMSQueueDictionary alloc] initWithStoreClass:[XMSModelTransformPair class]];
    [XMSModelTransform addTransPair:qd forModelIdentificationKey:[cls modelIdentificationKey]];
    block(qd);
    
    NSArray *propertys = [NSObject getPropertyNameList:cls];
    
    for(XMSModelTransformPair *pair in qd)
    {
        if(pair.idValue != nil)
        {
            NSString *att = [NSObject getPropertyType:cls property:pair.idValue];
            if(att.length > 0)
            {
                ENSObjectPropertyType propertyType = [NSObject NSObjectPropertyType:att];
                pair.propertyType = propertyType;
            }
#ifdef DEBUG
            else
            {
                NSAssert(YES, ([NSString stringWithFormat:@"%@ %@ 没有找到对应的property",NSStringFromClass(cls),pair.idKey]));
            }
#endif
        }
        else
        {
            NSString *key = pair.idKey;
            NSRange range = [key rangeOfString:@"xw"];
            if(range.location != NSNotFound && range.location == 0)
                key = [key substringFromIndex:range.length];
            key = [key lowercaseString];
            
            BOOL find = NO;
            
            for(NSString *property in propertys)
            {
                NSString *tmp = [property lowercaseString];
                if([tmp isEqualToString:key])
                {
                    NSString *att = [NSObject getPropertyType:cls property:property];
                    ENSObjectPropertyType propertyType = [NSObject NSObjectPropertyType:att];
                    
                    pair.idValue = property;
                    pair.propertyType = propertyType;
                    
                    find = YES;
                    
                    break;
                }
            }
#ifdef DEBUG
        NSAssert(find, ([NSString stringWithFormat:@"%@ %@ 没有找到对应的property",NSStringFromClass(cls),key]));
#endif
        }
    }
}

+(void)registerModelTransformOperationKeyType:(void(^)(NSString *key,NSString *property,NSUInteger opType))block
{
}

+(NSString*)modelIdentificationKey
{
    return @"";
}

-(XMSQueueDictionary*)modelTransformValueForOperateType:(XMSModelTransformOpType)opType
{
    XMSQueueDictionary *kv = [[[XMSQueueDictionary alloc] initWithStoreClass:[XMSModelTransformPair class]] autorelease_mm];

    XMSQueueDictionary *trasPair = [XMSModelTransform transPairForModelIdentificationKey:[[self class] modelIdentificationKey]];
    for (NSUInteger i = 0; i < trasPair.count; i++)
    {
        XMSModelTransformPair *pair = (XMSModelTransformPair *) [trasPair kvPairAtIndex:i];
        if((pair.opType & opType) == opType)
        {
            id value = [self valueForKey:(NSString *) pair.idValue];
            XMSModelTransformPair *p = [[pair copy] autorelease_mm];
            p.idValue = value;
            [kv addKvPair:p];
        }
    }

    return kv;
}

-(XMSQueueDictionary*)modelTransformValueForOperationKeys:(NSArray*)operationKeys
{
    XMSQueueDictionary *kv = [[[XMSQueueDictionary alloc] initWithStoreClass:[XMSModelTransformPair class]] autorelease_mm];
    
    XMSQueueDictionary *trasPair = [XMSModelTransform transPairForModelIdentificationKey:[[self class] modelIdentificationKey]];
    
    if (operationKeys.count > 0)
    {
        [operationKeys enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
        {
             for (NSUInteger i = 0; i < trasPair.count; i++)
             {
                 XMSModelTransformPair *pair = (XMSModelTransformPair *) [trasPair kvPairAtIndex:i];
                 if ([(NSString *) obj isEqualToString:(NSString *) pair.idKey] == YES)
                 {
                     id value = [self valueForKey:(NSString *) pair.idValue];
                     XMSModelTransformPair *p = [[pair copy] autorelease_mm];
                     p.idValue = value;
                     [kv addKvPair:p];
                     break;
                 }
             }
         }];
    }
    else
    {
        for (NSUInteger i = 0; i < trasPair.count; i++)
        {
            XMSModelTransformPair *pair = (XMSModelTransformPair *) [trasPair kvPairAtIndex:i];
            id value = [self valueForKey:(NSString *) pair.idValue];
            XMSModelTransformPair *p = [[pair copy] autorelease_mm];
            p.idValue = value;
            [kv addKvPair:p];
        }
    }
    
    return kv;
}

+(XMSQueueDictionary*)modelTransformForOperationType:(XMSModelTransformOpType)opType
{
    XMSQueueDictionary *kv = [[[XMSQueueDictionary alloc] initWithStoreClass:[XMSModelTransformPair class]] autorelease_mm];
    
    XMSQueueDictionary *trasPair = [XMSModelTransform transPairForModelIdentificationKey:[[self class] modelIdentificationKey]];
    
    for (NSUInteger i = 0; i < trasPair.count; i++)
    {
        XMSModelTransformPair *pair = (XMSModelTransformPair *) [trasPair kvPairAtIndex:i];
        if((pair.opType & opType) == opType)
        {
            XMSModelTransformPair *pair = (XMSModelTransformPair *) [trasPair kvPairAtIndex:i];
            [kv addKvPair:[[pair copy] autorelease_mm]];
        }
    }
    
    return kv;
}

+(XMSQueueDictionary*)modelTransformForOperationKeys:(NSArray*)operationKeys
{
    XMSQueueDictionary *kv = [[[XMSQueueDictionary alloc] initWithStoreClass:[XMSModelTransformPair class]] autorelease_mm];
    
    XMSQueueDictionary *trasPair = [XMSModelTransform transPairForModelIdentificationKey:[[self class] modelIdentificationKey]];
    
    if (operationKeys.count > 0)
    {
        [operationKeys enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
        {
            for (NSUInteger i = 0; i < trasPair.count; i++)
            {
                XMSModelTransformPair *pair = (XMSModelTransformPair *) [trasPair kvPairAtIndex:i];
                if ([(NSString *) obj isEqualToString:(NSString *) pair.idKey] == YES)
                {
                    [kv addKvPair:[[pair copy] autorelease_mm]];
                    break;
                }
            }
        }];
    }
    else
    {
        for (NSUInteger i = 0; i < trasPair.count; i++)
        {
            XMSModelTransformPair *pair = (XMSModelTransformPair *) [trasPair kvPairAtIndex:i];
            [kv addKvPair:[[pair copy] autorelease_mm]];
        }
    }
    return kv;
}

@end

@implementation NSArray (JSONArrayTransform)

-(NSArray*)JSONArrayTransformToObjArray:(Class)cls
{
    return [self JSONArrayTransformToObjArray:cls complexType:^id(NSString *key, ENSObjectPropertyType propertyType, id value)
    {
        return nil;
    }];
}

-(NSArray*)JSONArrayTransformToObjArray:(Class)cls accordingToKeys:(NSArray*)keys
{
    XMSQueueDictionary *qdSet = [cls modelTransformForOperationKeys:keys];
    NSArray* ar =[XMSJSONTransformObj JSONObjs:self transformToProtocolObj:cls accordingToColPropertyPair:qdSet complexType:^id(NSString *key, ENSObjectPropertyType propertyType, id complexType)
    {
        return nil;
    }];
    return ar;
}

-(NSArray*)JSONArrayTransformToObjArray:(Class)cls complexType:(id (^)(NSString *key, ENSObjectPropertyType propertyType, id value))complexType
{
    XMSQueueDictionary *qdSet = [cls modelTransformForOperationType:XMSModelTransformOpTypeNetAll];
    NSArray* ar =[XMSJSONTransformObj JSONObjs:self transformToProtocolObj:cls accordingToColPropertyPair:qdSet complexType:complexType];
    return ar;
}

-(NSArray*)JSONArrayTransformToObjArray:(Class)cls accordingToKeys:(NSArray*)keys complexType:(id (^)(NSString *key, ENSObjectPropertyType propertyType, id value))complexType
{
    XMSQueueDictionary *qdSet = [cls modelTransformForOperationKeys:keys];
    NSArray* ar =[XMSJSONTransformObj JSONObjs:self transformToProtocolObj:cls accordingToColPropertyPair:qdSet complexType:complexType];
    return ar;
}

@end

@implementation NSDictionary (JSONDictionaryTransform)

-(id)JSONDictionaryTransformToObj:(Class)cls
{
    return [self JSONDictionaryTransformToObj:cls complexType:^id(NSString *key, ENSObjectPropertyType propertyType, id value)
    {
        return nil;
    }];
}

-(id)JSONDictionaryTransformToObj:(Class)cls accordingToKeys:(NSArray*)keys
{
    return [self JSONDictionaryTransformToObj:cls accordingToKeys:keys complexType:^id(NSString *key, ENSObjectPropertyType propertyType, id value)
    {
        return nil;
    }];
}

-(id)JSONDictionaryTransformToObj:(Class)cls complexType:(id (^)(NSString *key, ENSObjectPropertyType propertyType, id value))complexType
{
    NSArray *ar = [@[self] JSONArrayTransformToObjArray:cls complexType:complexType];
    if(ar.count > 0)
        return ar[0];
    return nil;
}

-(id)JSONDictionaryTransformToObj:(Class)cls accordingToKeys:(NSArray*)keys complexType:(id (^)(NSString *key, ENSObjectPropertyType propertyType, id value))complexType
{
    NSArray *ar = [@[self] JSONArrayTransformToObjArray:cls accordingToKeys:keys complexType:complexType];
    if(ar.count > 0)
        return ar[0];
    return nil;
}

@end